# 线程安全问题
# 1. 线程安全
# 2. 线程不安全
# 3. 线程锁

# 线程安全
# 1. 线程安全：多个线程同时访问共享资源，不会出现问题
# 2. 线程不安全：多个线程同时访问共享资源，出现问题
# 3. 线程锁：保证多个线程同时访问共享资源时，只有一个线程可以访问，其他线程需要等待

# 线程锁
# 1. 线程锁：保证多个线程同时访问共享资源时，只有一个线程可以访问，其他线程需要等待
# 2. 线程锁的使用：使用threading模块中的Lock类
# 3. 线程锁的使用：使用threading模块中的RLock类
# 4. 线程锁的使用：使用threading模块中的Condition类
# 5. 线程锁的使用：使用threading模块中的Semaphore类
# 6. 线程锁的使用：使用threading模块中的BoundedSemaphore类

# 线程锁的使用
# 1. 线程锁的使用：使用threading模块中的Lock类


# 线程与进程
# 进程：操作系统分配资源的最小单位，一个进程可以包含多个线程，进程之间相互独立
# 线程：CPU调度的最小单位，一个进程中的多个线程共享进程的资源
# 线程是随机调度的，
# 线程之间切换的代价比进程大，所以线程适合处理一些短时间的任务，比如网络通信，数据库操作，文件操作等
# 进程之间切换的代价大，所以进程适合处理一些比较长的任务，比如图形界面，音频播放等
# 进程之间切换的代价大，所以进程适合处理一些比较长的任务，比如图形界面，音频播放等
# 线程之间切换的代价小，所以线程适合处理一些短时间的任务，比如网络通信，数据库操作，文件操作等  

# 生产者与消费者模式
# 线程创建
import threading
import time
import queue

queue = queue.Queue()
lock = threading.Lock()

# 定义一个名为task1的函数
# 生成者函数，添加数据到队列中
def task1():
    while True:
        # 获取锁
        lock.acquire()
        if queue.qsize() == 100:
            lock.release()
            continue
        # 将"data"放入队列
        queue.put("data")
        # 打印"生产者product put data"，当前线程的标识，队列的大小
        print("生产者product put data", threading.current_thread().ident, "@",queue.qsize())
        # 释放锁
        lock.release()


def task2():
    while True:
        # 获取锁
        lock.acquire()
        if queue.empty():
            lock.release()
            continue
        # 从队列中删除 
        # 阻塞，如果队列为空，则等待，直到队列中有数据
        queue.get()
        # 打印"消费者comsumer get data"，当前线程的标识，队列的大小
        print("消费者comsumer get data", threading.current_thread().ident,"@", queue.qsize())
        # 释放锁
        lock.release()

t1 = threading.Thread(target=task1)
t2 = threading.Thread(target=task2)
t3 = threading.Thread(target=task1)
t4 = threading.Thread(target=task2)
t5 = threading.Thread(target=task2)
# 启动线程
t1.start()
t2.start()
t3.start()
t4.start()
t5.start()
